home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 60 / IOPROG_60.ISO / soft / c++ / gsl-1.1.1-setup.exe / {app} / src / randist / gauss.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-05  |  3.1 KB  |  111 lines

  1. /* randist/gauss.c
  2.  * 
  3.  * Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough
  4.  * 
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or (at
  8.  * your option) any later version.
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <config.h>
  21. #include <math.h>
  22. #include <gsl/gsl_math.h>
  23. #include <gsl/gsl_rng.h>
  24. #include <gsl/gsl_randist.h>
  25.  
  26. /* Of the two methods provided below, I think the Polar method is more
  27.  * efficient, but only when you are actually producing two random
  28.  * deviates.  We don't produce two, because then we'd have to save one
  29.  * in a static variable for the next call, and that would screws up
  30.  * re-entrant or threaded code, so we only produce one.  This makes
  31.  * the Ratio method suddenly more appealing.  There are further tests
  32.  * one can make if the log() is slow.  See Knuth for details */
  33.  
  34. /* Both methods pass the statistical tests; but the polar method
  35.  * seems to be a touch faster on my home Pentium, EVEN though we
  36.  * are only using half of the available random deviates!
  37.  */
  38.  
  39. /* Polar (Box-Mueller) method; See Knuth v2, 3rd ed, p122 */
  40.  
  41. double
  42. gsl_ran_gaussian (const gsl_rng * r, const double sigma)
  43. {
  44.   double x, y, r2;
  45.  
  46.   do
  47.     {
  48.       /* choose x,y in uniform square (-1,-1) to (+1,+1) */
  49.  
  50.       x = -1 + 2 * gsl_rng_uniform (r);
  51.       y = -1 + 2 * gsl_rng_uniform (r);
  52.  
  53.       /* see if it is in the unit circle */
  54.       r2 = x * x + y * y;
  55.     }
  56.   while (r2 > 1.0 || r2 == 0);
  57.  
  58.   /* Box-Muller transform */
  59.   return sigma * y * sqrt (-2.0 * log (r2) / r2);
  60. }
  61.  
  62. /* Ratio method (Kinderman-Monahan); see Knuth v2, 3rd ed, p130 */
  63. /* K+M, ACM Trans Math Software 3 (1977) 257-260. */
  64.  
  65. double
  66. gsl_ran_gaussian_ratio_method (const gsl_rng * r, const double sigma)
  67. {
  68.   double u, v, x;
  69.  
  70.   do
  71.     {
  72.       v = gsl_rng_uniform (r);
  73.       do
  74.     {
  75.       u = gsl_rng_uniform (r);
  76.     }
  77.       while (u == 0);
  78.       /* Const 1.715... = sqrt(8/e) */
  79.       x = 1.71552776992141359295 * (v - 0.5) / u;
  80.     }
  81.   while (x * x > -4.0 * log (u));
  82.  
  83.   return sigma * x;
  84. }
  85.  
  86. double
  87. gsl_ran_gaussian_pdf (const double x, const double sigma)
  88. {
  89.   double u = x / fabs (sigma);
  90.   double p = (1 / (sqrt (2 * M_PI) * fabs (sigma))) * exp (-u * u / 2);
  91.   return p;
  92. }
  93.  
  94. double
  95. gsl_ran_ugaussian (const gsl_rng * r)
  96. {
  97.   return gsl_ran_gaussian (r, 1.0);
  98. }
  99.  
  100. double
  101. gsl_ran_ugaussian_ratio_method (const gsl_rng * r)
  102. {
  103.   return gsl_ran_gaussian_ratio_method (r, 1.0);
  104. }
  105.  
  106. double
  107. gsl_ran_ugaussian_pdf (const double x)
  108. {
  109.   return gsl_ran_gaussian_pdf (x, 1.0);
  110. }
  111.